home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / disk / misc / TurboDevice.lha / TurboDevice / TurboDev.asm < prev    next >
Encoding:
Assembly Source File  |  2000-10-07  |  41.9 KB  |  920 lines

  1.  ; /*
  2.  ; ##########################################################################
  3.  ; ####                                                                  ####
  4.  ; ####         TurboDevice - A resident RAM disk for the Amiga          ####
  5.  ; ####        =================================================         ####
  6.  ; ####                                                                  ####
  7.  ; #### TurboDev.asm                                                     ####
  8.  ; ####                                                                  ####
  9.  ; #### Version 1.00os  --  May 04, 1991                                 ####
  10.  ; ####                                                                  ####
  11.  ; #### Copyright (C) 1990  Thomas Dreibholz                             ####
  12.  ; ####               1991  Molbachweg 7                                 ####
  13.  ; ####                     51674 Wiehl/Germany                          ####
  14.  ; ####                     EMail: Dreibholz@bigfoot.com                 ####
  15.  ; ####                     WWW:   http://www.bigfoot.com/~dreibholz     ####
  16.  ; ####                                                                  ####
  17.  ; ##########################################################################
  18.  ; */
  19.  ;/***************************************************************************
  20.  ; *                                                                         *
  21.  ; *   This program is free software; you can redistribute it and/or modify  *
  22.  ; *   it under the terms of the GNU General Public License as published by  *
  23.  ; *   the Free Software Foundation; either version 2 of the License, or     *
  24.  ; *   (at your option) any later version.                                   *
  25.  ; *                                                                         *
  26.  ; ***************************************************************************/
  27.  
  28.  ; #######################################################
  29.  ; ##                                                   ##
  30.  ; ##            Das Turbo-Drive-System                 ##
  31.  ; ##            ======================                 ##
  32.  ; ##                                                   ##
  33.  ; ##  Entwicklungszeit:     21 Monate                  ##
  34.  ; ##  Fertigstellung:       4. Mai 1991  18:10:18 Uhr  ##
  35.  ; ##  Aktuelle Version:     29. Jun 1991               ##
  36.  ; ##                                                   ##
  37.  ; #######################################################
  38.  
  39.  ; Diese Dateien werden vom Assembler eingebunden
  40.  
  41.  include "exec/types.i"
  42.  include "exec/initializers.i"
  43.  include "exec/libraries.i"
  44.  include "exec/lists.i"
  45.  include "exec/nodes.i"
  46.  include "exec/resident.i"
  47.  include "exec/alerts.i"
  48.  include "exec/ables.i"
  49.  include "exec/devices.i"
  50.  include "exec/io.i"
  51.  include "exec/memory.i"
  52.  include "exec/errors.i"
  53.  include "libraries/dos.i"
  54.  include "libraries/dosextens.i"
  55.  
  56.  ; Es folgen 2 Makros zum Aufrufen von Library-Funktionen
  57.  
  58. CALLSYS  MACRO
  59.  jsr _LVO%1(a6)
  60.  endm
  61. LINKSYS  MACRO
  62.  move.l a6,-(a7)
  63.  move.l %2,a6
  64.  jsr _LVO%1(a6)
  65.  move.l (a7)+,a6
  66.  endm
  67.  
  68.  ; XLIB wird zum Einbinden der Library-Offsets benutzt
  69.  
  70. XLIB  MACRO
  71.  XREF _LVO%1
  72.  endm
  73.  
  74.  ; TURBO_NUMUNITS gibt die Anzahl der verfügbaren Units an.
  75.  ; Das turbo.device stellt 50 Verwaltungseinheiten (Units)
  76.  ; zur Verfügung.
  77.  
  78. TURBO_NUMUNITS EQU 50
  79.  
  80.  ; TurboDev ist die Device-Struktur die das Device verwaltet.
  81.  ; in fd_Units befinden sich Zeiger auf die einzelnen Unit-
  82.  ; -Strukturen.
  83.  
  84.  STRUCTURE TurboDev,LIB_SIZE
  85.   ULONG  td_SysLib                    ; exec.library
  86.   ULONG  td_DosLib                    ; dos.library
  87.   ULONG  td_SegList                   ; Segmentliste
  88.   ULONG  td_Resident                  ; Resident (nicht immer belegt!)
  89.   UBYTE  td_Flags                     ; Flags
  90.   UBYTE  td_DriveNum                  ; nächste Namennummer
  91.   STRUCT td_Units,TURBO_NUMUNITS*4    ; Zeiger auf Units
  92.  LABEL TurboDev_SIZE
  93.  
  94.  ; TurboDevMsg wird für den Unit-Prozeß benötigt.
  95.  
  96.  STRUCTURE TurboDevMsg,MN_SIZE
  97.   APTR tdm_Device                     ; Zeiger auf Device
  98.   APTR tdm_Unit                       ; Zeiger auf Unit
  99.  LABEL TurboDevMsg_SIZE
  100.  
  101.  ; TurboDevUnit ist die Struktur zur Verwaltung der einzelnen
  102.  ; Verwaltungseinheiten (Units).
  103.  
  104.  STRUCTURE TurboDevUnit,UNIT_SIZE
  105.   UBYTE  tdu_UnitNum                  ; Unit-Nummer
  106.   UBYTE  tdu_pad                      ; Füllbyte
  107.   STRUCT tdu_Msg,TurboDevMsg_SIZE     ; TurboDevMsg
  108.   APTR   tdu_Process                  ; Unit-Prozeß
  109.   LONG   tdu_LastComm                 ; Letztes Kommando für LastComm
  110.   LONG   tdu_Size                     ; Kapazität des Laufwerks (Bytes)
  111.   ULONG  tdu_NumTracks                ; Anzahl der Tracks
  112.   ULONG  tdu_Position                 ; Lese/Schreibkopf-Position
  113.   APTR   tdu_Memory                   ; Zeiger auf den Speicherbereich
  114.  LABEL TurboDevUnit_SIZE
  115.  
  116.  ; Mit den Funktionen Stop und Start läßt sich die Verarbeitung
  117.  ; anhalten. In UNIT_FLAGS wird FDUF_STOPPED gesetzt.
  118.  
  119.  BITDEF TDU,STOPPED,2                 ; Stop-Bit
  120.  
  121. TURBONAME MACRO                       ; Name des Turbo-Devices
  122.  dc.b 'turbo.device',0
  123.  endm
  124.  
  125.  ; Diese Funktionen werden vom Linker eingebunden.
  126.  
  127.  XREF _GetMemory                      ; Funktion zum Organisieren des Speichers
  128.  XREF _GetDriveSize                   ; Funktion zur Kapazitätsberechnung
  129.  XLIB OpenLibrary                     ; Library öffnen
  130.  XLIB CloseLibrary                    ; Library schließen
  131.  XLIB Alert                           ; Guru ausgeben
  132.  XLIB FreeMem                         ; Speicher freigeben
  133.  XLIB Remove                          ; Node entfernen
  134.  XLIB FindTask                        ; Task suchen
  135.  XLIB AllocMem                        ; Speicher belegen
  136.  XLIB CreateProc                      ; Prozeß erzeugen
  137.  XLIB PutMsg                          ; Message senden
  138.  XLIB RemTask                         ; Task entfernen
  139.  XLIB ReplyMsg                        ; Message zurücksenden
  140.  XLIB Signal                          ; Signale setzen
  141.  XLIB GetMsg                          ; Message erwarten
  142.  XLIB Wait                            ; Auf Signal warten
  143.  XLIB WaitPort                        ; Auf Message warten
  144.  XLIB AllocSignal                     ; Signal belegen
  145.  XLIB SetTaskPri                      ; Taskpriorität setzen
  146.  XLIB Permit                          ; Multitasking zulassen
  147.  
  148.  INT_ABLES
  149.  
  150.  ; Damit das Device, wenn er versehentlich gestartet wurde,
  151.  ; keinen Absturz erzeugt, wird das Device in START wieder
  152.  ; beendet.
  153.  
  154. START:
  155.  move.l #$20000,d0                    ; $20000 in d0
  156. 1$:                                   ; Schleife
  157.  move.w #$0F00,$DFF180                ; Rot in Farbregister 0
  158.  subq.l #1,d0                         ; 1 subtrahieren
  159.  tst.l d0                             ; ist d0=0 ?
  160.  bne 1$                               ; Nein, dann zu 1$
  161.  moveq.l #0,d0                        ; Keine Fehlermeldung
  162.  rts                                  ; Rücksprung
  163.  
  164. PRIORITY:   EQU 50                    ; Priorität
  165. VERSION:    EQU 35                    ; Version
  166. REVISION:   EQU 0                     ; Revision
  167.  
  168.  ; Hier beginnt die Resident-Struktur für das Device
  169.  
  170. InitTable:
  171.  dc.w RTC_MATCHWORD                   ; Code für Resident
  172.  dc.l InitTable                       ; Zeiger auf Anfang
  173.  dc.l EndCode                         ; Zeiger auf Ende
  174.  dc.b RTF_AUTOINIT                    ; Flag für autom. Installation
  175.  dc.b VERSION                         ; Version
  176.  dc.b NT_DEVICE                       ; Flag für Device
  177.  dc.b PRIORITY                        ; Priorität
  178.  dc.l TurboName                       ; Name der Devices
  179.  dc.l idString                        ; Zeiger auf Kommentar
  180.  dc.l Init                            ; Zeiger auf Intallationstabelle
  181.  
  182.  ; Hier stehen die Namen für die Installation
  183.  
  184. TurboName:  TURBONAME
  185. idString: dc.b 'turbo.device 35.0 (17 Okt 1991)',13,10,0   ; Kommentar
  186. dosName:  dc.b "dos.library",0        ; Name der dos.library
  187.  ds.w 0                               ; Auf gerade Adresse
  188.  
  189. EndCode:                              ; Ende der Resident-Struktur
  190.  
  191. Init:                                 ; Installationstabelle
  192.  dc.l TurboDev_SIZE                   ; Größe der Device-Struktur
  193.  dc.l funcTable                       ; Funktionstabelle
  194.  dc.l dataTable                       ; Datentabelle
  195.  dc.l InitRoutine                     ; Zeiger auf Installationsroutine
  196.  
  197. funcTable:                            ; Funktionstabelle
  198.  dc.l Open                            ; Öffnen des Devices
  199.  dc.l Close                           ; Schließen des Devices
  200.  dc.l Expunge                         ; Entfernen des Devices
  201.  dc.l Null                            ; Unbenutzte Funktion
  202.  dc.l BeginIO                         ; Kommandohandler
  203.  dc.l AbortIO                         ; Abbruch einer Funktion
  204.  dc.l CopyMemFast                     ; Kopierroutine (512 Bytes/Durchlauf)
  205.  dc.l CopyMemSlow                     ; Kopierroutine (byteweise)
  206.  dc.l CheckUnit                       ; Unit gültig ?
  207.  dc.l -1                              ; Ende der Tabelle
  208.  
  209. dataTable:                            ; Datentabelle
  210.  INITBYTE LH_TYPE,NT_DEVICE           ; Typ der Tabelle
  211.  INITLONG LN_NAME,TurboName           ; Name
  212.  INITBYTE LIB_FLAGS,LIBF_SUMUSED!LIBF_CHANGED ; Flags
  213.  INITWORD LIB_VERSION,VERSION         ; Version
  214.  INITWORD LIB_REVISION,REVISION       ; Revision
  215.  INITLONG LIB_IDSTRING,idString       ; Kommentar
  216.  dc.l 0                               ; Ende der Tabelle
  217.  
  218.  ; ========================================================
  219.  ; = Hier steht die Installationsroutine, die beim ersten =
  220.  ; = Zugriff auf das Device aufgerufen wird, um die Stru- =
  221.  ; = ktur vollständig zu installieren.                    =
  222.  ; = Ihe Parameter sind:                                  =
  223.  ; =  => D0 = Zeiger auf die Device-Struktur              =
  224.  ; =  => A0 = Zeiger auf die Segmentliste                 =
  225.  ; =  => A6 = Zeiger auf die exec.library                 =
  226.  ; =                                                      =
  227.  ; =  <= D0 = Zeiger auf die Device-Struktur              =
  228.  ; ========================================================
  229.  
  230. InitRoutine:
  231.  move.l a5,-(a7)                      ; a5 retten
  232.  move.l d0,a5                         ; Device nach a5
  233.  move.l a6,td_SysLib(a5)              ; exec.library in SysLib
  234.  move.l a0,td_SegList(a5)             ; Segmentliste in SegList
  235.  lea    dosName(pc),a1                ; Name der dos.library
  236.  moveq  #0,d0                         ; Version=0
  237.  CALLSYS OpenLibrary                  ; Library öffnen
  238.  move.l d0,td_DosLib(a5)              ; dos.library in DosLib
  239.  bne.s Dos_OK                         ; Konnte Library geöffnet werden ?
  240.  ALERT AG_OpenLib!AO_DOSLib           ; Nein, dann Reset
  241. Dos_OK:                               ; Ja
  242.  move.b #1,td_DriveNum(a5)            ; Start-Namensnummer ist 1
  243.  move.l a5,d0                         ; Device nach d0
  244.  move.l (a7)+,a5                      ; a5 freigeben
  245.  rts                                  ; Rücksprung
  246.  
  247.  ; =====================================================
  248.  ; = Die Open-Funktion wird immer aufgerufen, wenn ein =
  249.  ; = Programm das Turbo-Device öffnet. Sie installiert =
  250.  ; = die Unit-Struktur.                                =
  251.  ; = Ihre Parameter sind:                              =
  252.  ; =  => D0 = Unitnummer                               =
  253.  ; =  => D1 = Flags                                    =
  254.  ; =  => A1 = Zeiger auf die IOStdReq-Struktur         =
  255.  ; =  => A6 = Zeiger auf das Device                    =
  256.  ; =====================================================
  257.  
  258. Open:
  259.  movem.l d2/a2-a4,-(a7)               ; Register retten
  260.  move.l a1,a2                         ; IOStdReq nach a2
  261.  moveq #TURBO_NUMUNITS,d2               ; Unitanzahl nach d2
  262.  cmp.l d2,d0                          ; Unitnummer gültig ?
  263.  bcc.s Open_error                     ; Nein, dann springe zu Open_error
  264.  move.l d0,d2                         ; Unitnummer nach d2
  265.  lsl.l #2,d0                          ; Nummer mit 4 multiplizieren
  266.  lea td_Units(a6,d0.l),a4             ; Unit-Adresse nach a4
  267.  move.l (a4),d0                       ; Adresse nach d0
  268.  bne.s Open_ok                        ; zu Open_ok springen
  269.  bsr InitUnit                         ; Unit installieren
  270.  move.l (a4),d0                       ; Unit nach d0
  271.  beq.s Open_error                     ; Fehler? Dann springe zum Open_error
  272. Open_ok:                              ; Open_ok:
  273.  move.l d0,a3                         ; Unit nach a3
  274.  move.l d0,IO_UNIT(a2)                ; Unit installieren
  275.  addq.w #1,LIB_OPENCNT(a6)            ; Device-Benutzerzähler +1
  276.  addq.w #1,UNIT_OPENCNT(a3)           ; Unit-Benutzerzäher +1
  277.  bclr   #LIBB_DELEXP,td_Flags(a6)     ; Entfernungsflag löschen
  278. Open_end:                             ; Open_end:
  279.  movem.l (a7)+,d2/a2-a4               ; Register freigeben
  280.  rts                                  ; Rücksprung
  281.  
  282.  ; Wenn ein Fehler aufgetreten ist, dann wird zu
  283.  ; Open_error gesprungen.
  284.  
  285. Open_error:                           ; Open_error:
  286.  move.b #IOERR_OPENFAIL,IO_ERROR(a2)  ; Fehler in io_Error
  287.  bra.s  Open_end                      ; Zum Ende springen
  288.  
  289.  ; ========================================================
  290.  ; = Wenn das Device über CloseDevice() geschlossen wird, =
  291.  ; = wird Close aufgerufen. Diese Funktion gibt den       =
  292.  ; = Speicher für das Unit frei, wenn Kein Programm mehr  =
  293.  ; = auf das Unit zugreift. Wird von keinem Programm mehr =
  294.  ; = auf das Device zugegriffen und ist das LIBB_DELEXP-  =
  295.  ; = -Flag gesetzt, dann wird das Device mit Expunge      =
  296.  ; = entfernt.                                            =
  297.  ; = Ihre Parameter sind:                                 =
  298.  ; =  => A1 = Zeiger auf die IOStdReq-Struktur            =
  299.  ; =  => Zeiger auf die Device-Struktur                   =
  300.  ; =                                                      =
  301.  ; =  <= Zeiger auf die Segmentliste                      =
  302.  ; ========================================================
  303.  
  304. Close:
  305.  movem.l a2-a3,-(a7)                  ; Register retten
  306.  move.l a1,a2                         ; IOStdReq nach a2
  307.  move.l IO_UNIT(a2),a3                ; Unit nach a3
  308.  moveq.l #-1,d0                       ; Segmentlist=-1
  309.  move.l d0,IO_UNIT(a2)                ; Unit=-1
  310.  move.l d0,IO_DEVICE(a2)              ; Device=-1
  311.  subq.w #1,UNIT_OPENCNT(a3)           ; Unit-Zugriffszähler-1
  312.  bne.s 1$                             ; Wenn nicht 0, dann springe zu 1$
  313.  bsr ExpungeUnit                      ; Springe zu ExpungeUnit
  314. 1$:                                   ; 1$:
  315.  clr.l d0                             ; Segmentliste=0
  316.  subq.w #1,LIB_OPENCNT(a6)            ; Device-Zugriffszähler+1
  317.  bne.s Close_end                      ; Wenn nicht 0, dann Ende
  318.  btst #LIBB_DELEXP,td_Flags(a6)       ; Ist LIBB_DELEXP gesetzt ?
  319.  beq.s Close_end                      ; Nein, dann Close_end
  320.  bsr Expunge                          ; Springe zu Expunge
  321. Close_end:                            ; Close_end:
  322.  movem.l (a7)+,a2-a3                  ; Register freigeben
  323.  rts                                  ; Rücksprung
  324.  
  325.  ; =====================================================
  326.  ; = Expunge entfernt das Device und gibt den Speicher =
  327.  ; = wieder frei.                                      =
  328.  ; = Ihre Parameter sind:                              =
  329.  ; =  => A6 = Zeiger auf das Device                    =
  330.  ; =                                                   =
  331.  ; =  <= D0 = Zeiger auf die Segmentliste              =
  332.  ; =====================================================
  333.  
  334. Expunge:
  335.  movem.l d2/a5-a6,-(a7)               ; Register retten
  336.  move.l a6,a5                         ; Device nach a5
  337.  move.l td_SysLib(a5),a6              ; exec.library nach a6
  338.  tst.w  LIB_OPENCNT(a5)               ; Ist Zugriffszähler=0 ?
  339.  beq 1$                               ; Ja, dann springe zu 1$
  340.  bset #LIBB_DELEXP,td_Flags(a5)       ; LIBB_DELEXP-Flag löschen
  341.  clr.l d0                             ; Segmentliste=0
  342.  bra.s Expunge_end                    ; Springe zu Expunge_end
  343. 1$:                                   ; 1$:
  344.  move.l td_SegList(a5),d2             ; SegList nach d2
  345.  move.l a5,a1                         ; Device nach a1
  346.  CALLSYS Remove                       ; Device aus DeviceList entfernen
  347.  move.l td_DosLib(a5),a1              ; dos.library nach a1
  348.  CALLSYS CloseLibrary                 ; Library schließen
  349.  move.l a5,a1                         ; Device nach a1
  350.  clr.l d0                             ; d0=0
  351.  move.w LIB_NEGSIZE(a5),d0            ; Negative Größe nach d0
  352.  sub.w d0,a1                          ; Negative Größe vom Device abziehen
  353.  add.w LIB_POSSIZE(a5),d0             ; Positive Größe nach d0
  354.  CALLSYS FreeMem                      ; Speicher freigeben
  355.  move.l d2,d0                         ; Segmentliste nach d2
  356. Expunge_end: movem.l (a7)+,d2/a5-a6   ; Register freigeben
  357.  rts                                  ; Rücksprung
  358.  
  359.  ; Diese Funktion (ExtFuncDev) ist nicht belegt.
  360.  
  361. Null:
  362.  clr.l d0                             ; Rückgabe=0
  363.  rts                                  ; Rücksprung
  364.  
  365. TURBOPROCSTACK   EQU $200             ; Stackgröße
  366. TURBOPROCPRI     EQU 110              ; Priorität
  367.  
  368.  ; ===========================================================
  369.  ; = InitUnit erstellt den neuen Prozeß für die Verwaltungs- =
  370.  ; = einheit und die neue Unit-Struktur. Dem Prozeß wird die =
  371.  ; = Adresse des Devices in einer Message mitgeteilt. Die    =
  372.  ; = Message ist in der Unit-Struktur integriert.            =
  373.  ; = Ihre Parameter sind:                                    =
  374.  ; =  => D2 = Unitnummer                                     =
  375.  ; =  => A6 = Zeiger auf Device                              =
  376.  ; ===========================================================
  377.  
  378. InitUnit:
  379.  movem.l d2-d4,-(a7)                  ; Register retten
  380.  move.l #TurboDevUnit_SIZE,d0         ; Unitgröße is d0
  381.  move.l #MEMF_PUBLIC!MEMF_CLEAR,d1    ; Flags in d1
  382.  LINKSYS AllocMem,td_SysLib(a6)       ; Speicher belegen
  383.  tst.l  d0                            ; Konnte Speicher belegt werden ?
  384.  beq InitUnit_end                     ; Nein,dann Ende
  385.  move.l d0,a3                         ; Speicher nach a3
  386.  move.l #0,tdu_Position(a3)           ; Lese/Schreibkopf steht auf 0
  387.  movem.l d1-d7/a0-a6,-(sp)            ; Register retten
  388.  move.l a3,-(sp)                      ; Unit auf Stapel
  389.  ext.w d2                             ; Unitnummer auf Wortgröße
  390.  ext.l d2                             ; Unitnummer auf Langwortgröße
  391.  move.l d2,-(sp)                      ; Unitnummer auf Stapel
  392.  move.l a6,-(sp)                      ; Device auf Stapel
  393.  move.l $4,-(sp)                      ; ExecBase auf Stapel
  394.  jsr _GetMemory                       ; Speicher organisieren
  395.  add.w #16,sp                         ; Stapel erhöhen
  396.  movem.l (sp)+,d1-d7/a0-a6            ; Register freigeben
  397.  tst.l d0                             ; Konnte Speicher belegt werden ?
  398.  beq InitUnit_end                     ; Nein, dann Ende
  399.  move.l d0,tdu_Memory(a3)             ; Speicher in tdu_Memory
  400.  clr.l tdu_LastComm(a3)               ; tdu_LastComm=0
  401.  move.b d2,tdu_UnitNum(a3)            ; Unitnummer in UnitNum
  402.  move.l #TURBOPROCSTACK,d4            ; Stack in d4
  403.  move.l #TurboProc_SegList,d3         ; SegList in d3
  404.  lsr.l #2,d3                          ; Durch 4 teilen
  405.  moveq #TURBOPROCPRI,d2               ; Priorität in d2
  406.  move.l #TurboName,d1                 ; Name in d1
  407.  LINKSYS CreateProc,td_DosLib(a6)     ; Prozeß erstellen
  408.  tst.l  d0                            ; Konnte Prozeß erstellt werden ?
  409.  beq InitUnit_FreeUnit                ; Nein, dann Ende
  410.  move.l d0,tdu_Process(a3)            ; Prozeß in tdu_Prozeß
  411.  move.l d0,a0                         ; Prozeß nach a0
  412.  lea    -pr_MsgPort(a0),a0            ; MsgPort abziehen
  413.  move.l a0,MP_SIGTASK(a3)             ; Prozeß in MP_SIGTASK
  414.  move.b #PA_IGNORE,MP_FLAGS(a3)       ; MP_FLAGS=PA_IGNORE
  415.  lea    MP_MSGLIST(a3),a1             ; MsgList nach a1
  416.  NEWLIST a1                           ; Neue Liste erstellen
  417.  lea    tdu_Msg(a3),a1                ; Message nach a1
  418.  move.l a3,tdm_Unit(a1)               ; Unit in tdm_Unit
  419.  move.l a6,tdm_Device(a1)             ; Device in tdm_Device
  420.  move.l d0,a0                         ; Messageport nach a0
  421.  LINKSYS PutMsg,td_SysLib(a6)         ; Message senden
  422.  clr.l d0                             ; d0=0
  423.  move.b tdu_UnitNum(a3),d0            ; UnitNum nach d0
  424.  lsl.l #2,d0                          ; Mal 4
  425.  move.l a3,td_Units(a6,d0.l)          ; Unit in td_Unit
  426. InitUnit_end:                         ; Ende:
  427.  movem.l (a7)+,d2-d4                  ; Register freigeben
  428.  rts                                  ; Rücksprung
  429.  
  430. InitUnit_FreeUnit:                    ; Fehler:
  431.  bsr FreeUnit                         ; Unit freigeben
  432.  bra.s InitUnit_end                   ; Zum Ende springen
  433.  
  434.  ; #####################################################
  435.  ; # FreeUnit gibt den Speicher der Unit-Struktur frei #
  436.  ; # Ihr Parameter ist:                                #
  437.  ; #  => A3 = Zeiger auf die Unit-Struktur             #
  438.  ; #####################################################
  439.  
  440. FreeUnit:
  441.  move.l tdu_Memory(a3),a1             ; Speicher in a1
  442.  move.l tdu_Size,d0                   ; Größe in d0
  443.  LINKSYS FreeMem,td_SysLib(a6)        ; Speicher freigeben
  444.  move.l a3,a1                         ; Unit in a3
  445.  move.l #TurboDevUnit_SIZE,d0         ; Unitgröße in d0
  446.  LINKSYS FreeMem,td_SysLib(a6)        ; Speicher freigeben
  447.  rts                                  ; Rücksprung
  448.  
  449.  ; #####################################################
  450.  ; # ExpungeUnit entfernt eine Verwaltungseinheit, die #
  451.  ; # nicht mehr benötigt wird.                         #
  452.  ; # Ihre Parameter sind:                              #
  453.  ; #  => A3 = Zeiger auf Unit-Struktur                 #
  454.  ; #  => A6 = Zeiger auf Device                        #
  455.  ; #####################################################
  456.  
  457. ExpungeUnit:
  458.  move.l d2,-(a7)                      ; d2 retten
  459.  move.l tdu_Process(a3),a1            ; Prozeß nach a1
  460.  lea    -pr_MsgPort(a1),a1            ; MsgPort abziehen
  461.  LINKSYS RemTask,td_SysLib(a6)        ; Prozeß beenden
  462.  clr.l d2                             ; d2=0
  463.  move.b tdu_UnitNum(a3),d2            ; Unitnummer nach d2
  464.  bsr.s FreeUnit                       ; Unit freigeben
  465.  lsl.l #2,d2                          ; Unitnummer mit 4 multiplizieren
  466.  clr.l td_Units(a6,d2.l)              ; td_Unit löschen
  467.  move.l (a7)+,d2                      ; d2 freigeben
  468.  rts                                  ; Rücksprung
  469.  
  470.  ; =================================================
  471.  ; = cmdtable:                                     =
  472.  ; = Hier stehen die Befehle, die durch das Device =
  473.  ; = aufgerufen werden können. Die Befehle sind    =
  474.  ; = der Rehe nach in der Tabelle aufgeführt.      =
  475.  ; = Invalid ist der Befehl 0. Die Befehle Reset   =
  476.  ; = bis Flush sind Befehle, die im jedem Device   =
  477.  ; = vorhanden sind. Die Befehle Reset bis Prot-   =
  478.  ; = status müssen bei jedem Laufwerk vorhanden    =
  479.  ; = sein, da DOS diese Befehle für die Verwaltung =
  480.  ; = begötigt. Die Direkt-Befehle sind in der      =
  481.  ; = Konstante "DirektBefehle" mit oder verknüpft. =
  482.  ; = Alle in dieser Konstante aufgeführten Befehle =
  483.  ; = werden direkt ausgeführt, und nicht an den    =
  484.  ; = Prozeß geschickt.                             =
  485.  ; =================================================
  486.  
  487. cmdtable:
  488.  ; Hier stehen die Befehle, die alle Devices besitzen.
  489.  ; Die Befehle ab Motor sind für Laufwerke wichtig.
  490.  ; Sie werden vom DOS benutzt und müssen vorhanden
  491.  ; sein.
  492.  
  493.  dc.l Invalid      ; Invalid       Keine Funktion
  494.  dc.l MyReset      ; Reset         Keine Funktion
  495.  dc.l Read         ; Read          Block lesen
  496.  dc.l Write        ; Write         Block schreiben
  497.  dc.l Update       ; Update        Buffer schreiben
  498.  dc.l Clear        ; Clear         Buffer löschen
  499.  dc.l MyStop       ; Stop          Abarbeitung anhalten
  500.  dc.l Start        ; Start         Abarbeitung wieder starten
  501.  dc.l Flush        ; Flush         Alle Messages als Abgebrochen zurücksenden
  502.  dc.l Motor        ; Motor         Motor ein- und ausschalten
  503.  dc.l Seek         ; Seek          Schreib/Lesekopf positionieren
  504.  dc.l Write        ; Format        Track formatieren
  505.  dc.l Remove       ; Remove        Diskettenwechsel-Interrupt installiern
  506.  dc.l Status       ; ChangeNum:    Diskettenwechsel (0)
  507.  dc.l Status       ; ChangeState:  Diskette eingelegt (ja)
  508.  dc.l Status       ; ProtStatus:   Schreibschutz (aus)
  509.  
  510.  ; Hier beginnen die eigenen Befehle.
  511.  ; Sie sind für die Arbeit des DOS
  512.  ; mit dem Device unwichtig.
  513.  
  514.  dc.l RawRead      ; RawRead:      Byteweises lesen
  515.  dc.l RawWrite     ; RawWrite:     Byteweises schreiben
  516.  dc.l GetDriveType ; GetDriveType: Laufwerkstyp (=> 5.25 Zoll)
  517.  dc.l GetNumTracks ; GetNumTracks: Anzahl der Tracks
  518.  dc.l AddChangeInt ; Diskettenwechselinterrupt installieren
  519.  dc.l RemChangeInt ; Diskettenwechselinterrupt entfernen
  520.  dc.l LastComm     ; LastComm:     Letztes Kommando ermitteln
  521. cmdtableend:
  522.  
  523. DirektBefehle equ $1!$2!$10!$20!$40!$80!$100
  524.  
  525. FUNKANZ: EQU 23    ; 23 Befehle
  526.  
  527.  ; ==========================================================
  528.  ; = BeginIO ist die Funktion, die die Befehle verarbeitet. =
  529.  ; = Sie stellt die gültigkeit fest und bestimmt, ob der    =
  530.  ; = Befehl zum Prozeß des Units gesendet oder direkt aus-  =
  531.  ; = geführt wird.                                          =
  532.  ; = Ihre Parameter sind:                                   =
  533.  ; =  => A1 = Zeiger auf die IOStdReq-Strunktur             =
  534.  ; =  => A6 = Zeiger auf die Device-Struktur                =
  535.  ; ==========================================================
  536.  
  537. BeginIO:
  538.  move.l a3,-(a7)                   ; a3 retten
  539.  move.l IO_UNIT(a1),a3             ; Zeiger auf das Unit in a3
  540.  move.w IO_COMMAND(a1),d0          ; Kommando nach d0
  541.  bclr #15,d0                       ; Extended-Bit löschen
  542.  cmp.w #FUNKANZ,d0                 ; Ist Kommando gültig ?
  543.  bcc BeginIO_NoCmd                 ; Nein? Dann springe zu BeginIO_NoCmd
  544.  DISABLE a0                        ; Interrupts sperren
  545.  move.l #DirektBefehle,d1          ; Ist der Befehl ein Direkt-Befehl ?
  546.  btst d0,d1                        ; Ja ?
  547.  bne.s BeginIO_Immediate           ; Wenn Nein, dann springe
  548. BeginIO_QueueMsg:                  ; Ja.
  549.  bset #UNITB_INTASK,UNIT_FLAGS(a3) ; Unit-Bit setzen
  550.  bclr #IOB_QUICK,IO_FLAGS(a1)      ; Quick-Flag löschen
  551.  ENABLE a0                         ; Interrupts erlauben
  552.  move.l a3,a0                      ; Unit nach a0
  553.  LINKSYS PutMsg,td_SysLib(a6)      ; Message Senden
  554.  bra.s BeginIO_end                 ; Ende
  555.  
  556. BeginIO_Immediate:
  557.  ENABLE a0                         ; Interrupts erlauben
  558.  bsr PerformIO                     ; Befehl ausführen
  559. BeginIO_end: move.l (a7)+,a3       ; a3 wieder zurückgeben
  560.  rts                               ; Rücksprung
  561.  
  562. BeginIO_NoCmd:                     ; Kommandofehler
  563.  move.b #IOERR_NOCMD,IO_ERROR(a1)  ; Fehler in io_Error
  564.  bra.s BeginIO_end                 ; Zum Ende springen
  565.  
  566.  ; ===================================================
  567.  ; = PerformIO:                                      =
  568.  ; = Diese Funktion holt die Adresse des Befehls aus =
  569.  ; = der Tabelle und springt zu der angegebenen      =
  570.  ; = Adresse.                                        =
  571.  ; = Ihre Parameter sind:                            =
  572.  ; =  => A1 = Zeiger auf IOStdReq                    =
  573.  ; =  => A3 = Zeiger auf Unit-Struktur               =
  574.  ; =  => A6 = Zeiger auf Device                      =
  575.  ; ===================================================
  576.  
  577. PerformIO:
  578.  move.l a2,-(a7)                   ; a2 retten
  579.  move.l a1,a2                      ; IOStdReq nach a2
  580.  move.w IO_COMMAND(a2),d0          ; Kommando nach d0
  581.  lsl.w #2,d0                       ; mal 4
  582.  lea cmdtable(pc),a0               ; Kommandoadresse holen
  583.  move.l 00(a0,d0.w),a0             ; Adresse nach a0
  584.  jsr (a0)                          ; Befehl ausführen
  585.  move.l (a7)+,a2                   ; a2 freigeben
  586.  rts
  587.  
  588.  ; ====================================================
  589.  ; = TermIO wird zur Beendigung von jeder Funktion    =
  590.  ; = aufgerufen. Sie sendet, wenn der Befehl über den =
  591.  ; = Prozeß lief, die Message zurück.                 =
  592.  ; ====================================================
  593.  
  594. TermIO:
  595.  move.w IO_COMMAND(a1),d0          ; Kommando nach d0
  596.  move.w d0,d5                      ; und d5
  597.  ext.l d5                          ; auf Langwortgröße erweiten
  598.  move.l d5,tdu_LastComm(a3)        ; Kommando in tdu_LastComm
  599.  move.l #DirektBefehle,d1          ; Direktbefehlsmaske in d1
  600.  btst   d0,d1                      ; Direktbefehl ?
  601.  bne.s TermIO_Direkt               ; Ja
  602.  btst #UNITB_INTASK,UNIT_FLAGS(a3) ; Ging der Befehl über den Prozeß ?
  603.  bne.s TermIO_Direkt               ; Nein
  604.  bclr #UNITB_ACTIVE,UNIT_FLAGS(a3) ; Task freigeben
  605. TermIO_Direkt:
  606.  btst #IOB_QUICK,IO_FLAGS(a1)      ; Quick-Flag gesetzt ?
  607.  bne.s TermIO_end                  ; Nein, dann springe
  608.  LINKSYS ReplyMsg,td_SysLib(a6)    ; Message zurücksenden
  609. TermIO_end: rts                    ; Rücksprung
  610.  
  611.  ; Diese Routine ist zum Abbrechen eines laufenden Befehls
  612.  ; gedacht. Da das Abbrechen eines Befehls in Laufwerken
  613.  ; ist nicht sinnvoll ist, ist eine Abbruchfunktion nicht
  614.  ; implementiert.
  615.  
  616. AbortIO:                           ; Funktion zum Abbruch eines Kommandos
  617.  moveq #0,d0                       ; Kein Fehler
  618.  rts                               ; Rücksprung
  619.  
  620. CheckUnit:                         ; Unit belegt ?
  621.  lsl.l #2,d0                       ; Nummer*4
  622.  lea td_Units(a6,d0.l),a0          ; Unit nach a0
  623.  move.l (a0),d0                    ; a0 in d0
  624.  rts                               ; Rücksprung
  625.  
  626.  ; ================================================
  627.  ; = Hier beginnen die Device-Befehle, die durch  =
  628.  ; = den vorher installierten Prozeß oder durch   =
  629.  ; = BeginIO angesprungen werden.                 =
  630.  ; = Alle Befehle müssen mit TermIO abgeschlossen =
  631.  ; = werden!                                      =
  632.  ; = Die Parameter sind:                          =
  633.  ; = => A1 = Zeiger auf die IOStdReq-Struktur     =
  634.  ; = => A3 = Zeiger auf die Unit-Struktur         =
  635.  ; = => A6 = Zeiger auf die Device-Struktur       =
  636.  ; ================================================
  637.  
  638. MyReset:
  639. Invalid:                           ; Abarbeitung eines ungültigen Befehls
  640.  move.b #IOERR_NOCMD,IO_ERROR(a1)  ; IOERR_NOCMD nach io_Error
  641.  bsr TermIO                        ; Zu TermIO springen
  642.  rts                               ; Rücksprung
  643.  
  644. GetDriveType:                      ; Laufwerkstyp ermitteln
  645.  move.l #2,IO_ACTUAL(a1)           ; In einem Ram-Laufwerk gibt es keine
  646.  bsr TermIO                        ; Typen! Rückgabe als 5.25 Zoll.
  647.  rts
  648.  
  649. GetNumTracks:                      ; Anzahl der Tracks ermitteln
  650.  move.l tdu_NumTracks(a3),IO_ACTUAL(a1) ; Größe in Actual
  651.  bsr TermIO                        ; Zu TermIO springen
  652.  rts                               ; Rücksprung
  653.  
  654. LastComm:                          ; Letzten Kommando ermitteln
  655.  move.l tdu_LastComm(a3),IO_ACTUAL(a1)  ; Kommando in Actual
  656.  bsr TermIO                        ; Zu TermIO springen
  657.  rts                               ; Rücksprung
  658.  
  659. RawRead:                           ; Byteweises lesen
  660.  movem.l a0/a2/d0,-(sp)            ; Register retten
  661.  move.l tdu_Memory(a3),a0          ; Speicher in a0
  662.  add.l IO_OFFSET(a1),a0            ; Offset addieren
  663.  move.l IO_DATA(a1),a2             ; Daten in a2
  664.  move.l IO_LENGTH(a1),d0           ; Lange in d0
  665.  jsr CopyMemSlow
  666.  movem.l (sp)+,a0/a2/d0            ; Register freigeben
  667.  move.l IO_LENGTH(a1),IO_ACTUAL(a1); Länge in Actual
  668.  move.l IO_OFFSET(a1),tdu_Position(a3) ; Lesekopfposition
  669.  clr.b IO_ERROR(a1)                ; Keine Fehler
  670.  bsr TermIO                        ; Zu TermIO springen
  671.  rts                               ; Rücksprung
  672.  
  673. RawWrite:                          ; Byteweises lesen
  674.  movem.l a0/a2/d0,-(sp)            ; Register retten
  675.  move.l tdu_Memory(a3),a2          ; Speicher in a2
  676.  add.l IO_OFFSET(a1),a2            ; Offset addieren
  677.  move.l IO_DATA(a1),a0             ; Daten in a0
  678.  move.l IO_LENGTH(a1),d0           ; Länge in d0
  679.  jsr CopyMemSlow                   ; Speicher kopieren
  680.  movem.l (sp)+,a0/a2/d0            ; Register freigeben
  681.  move.l IO_LENGTH(a1),IO_ACTUAL(a1); Länge in Actual
  682.  move.l IO_OFFSET(a1),tdu_Position(a3) ; Schreibkopfposition
  683.  clr.b IO_ERROR(a1)                ; Keine Fehler
  684.  bsr TermIO                        ; Zu TermIO springen
  685.  rts                               ; Rücksprung
  686.  
  687. Read:                              ; Block lesen
  688.  movem.l a0/a2/d0,-(sp)            ; Register retten
  689.  move.l tdu_Memory(a3),a0          ; Speicher in a0
  690.  add.l IO_OFFSET(a1),a0            ; Offset addieren
  691.  move.l IO_DATA(a1),a2             ; Daten in a2
  692.  move.l IO_LENGTH(a1),d0           ; Länge in d0
  693.  jsr CopyMemFast                   ; Zur Kopierroutine springen
  694.  movem.l (sp)+,a0/a2/d0            ; Register freigeben
  695.  move.l IO_LENGTH(a1),IO_ACTUAL(a1); Länge in Actual
  696.  move.l IO_OFFSET(a1),tdu_Position(a3) ; Lesekopfposition
  697.  clr.b IO_ERROR(a1)                ; Keine Fehler
  698.  bsr TermIO                        ; Zu TermIO springen
  699.  rts                               ; Rücksprung
  700.  
  701. Write:                             ; Block schreiben
  702.  movem.l a0/a2/d0,-(sp)            ; Register retten
  703.  move.l tdu_Memory(a3),a2          ; Speicher in a2
  704.  add.l IO_OFFSET(a1),a2            ; Offset addieren
  705.  move.l IO_DATA(a1),a0             ; Daten in a0
  706.  move.l IO_LENGTH(a1),d0           ; Länge in d0
  707.  jsr CopyMemFast                   ; Zur Kopierroutine springen
  708.  movem.l (sp)+,a0/a2/d0            ; Register freigeben
  709.  move.l IO_LENGTH(a1),IO_ACTUAL(a1); Länge in Actual
  710.  move.l IO_OFFSET(a1),tdu_Position(a3) ; Schreibkopfposition
  711.  clr.b IO_ERROR(a1)                ; Keine Fehler
  712.  bsr TermIO                        ; Zu TermIO springen
  713.  rts                               ; Rücksprung
  714.  
  715.  ; ================================================
  716.  ; = CopyMemSlow:                                 =
  717.  ; = Diese Routine kopiert den Speicher für die   =
  718.  ; = Raw-Befehle. Sie kopiert byteweise und ist   =
  719.  ; = deshalb auch langsamer.                      =
  720.  ; = Ihre Parameter sind:                         =
  721.  ; =  => D0 = Länge                               =
  722.  ; =  => A0 = Quelladresse                        =
  723.  ; =  => A2 = Zieladresse                         =
  724.  ; ================================================
  725.  
  726. CopyMemSlow:                       ; Speicher Byteweise kopieren
  727.  tst.l d0                          ; Ist etwas zu kopieren ?
  728.  beq CopyMemSlow_Ende              ; Nein, dann Ende
  729. CopyMemSlow_Loop:                  ; Schleife
  730.  move.b (a0)+,(a2)+                ; a0 nach a2 und erhöhen
  731.  dbra d0,CopyMemSlow_Loop          ; Zurückzählen
  732. CopyMemSlow_Ende:                  ; Ende
  733.  rts                               ; Rücksprung
  734.  
  735.  ; ================================================
  736.  ; = CopyMemFast:                                 =
  737.  ; = Diese Routine ist das Kernstück des Devices. =
  738.  ; = Über sie werden alle Scheib -und Lesebefehle =
  739.  ; = abgewickelt. Sie kopiert 512 Bytes in einem  =
  740.  ; = Durchlauf!                                   =
  741.  ; = RawRead und RawWrite laufen nicht über diese =
  742.  ; = Funktion, weil sie auch einzelne Bytes lesen =
  743.  ; = können. Sie sind dadurch langsamer.          =
  744.  ; = Ihre Parameter sind:                         =
  745.  ; = => D0 = Länge                                =
  746.  ; = => A0 = Quelladresse                         =
  747.  ; = => A2 = Zieladresse                          =
  748.  ; ================================================
  749.  
  750.  ; INIT_COPY ist ein Macro, um die Routine zu installieren.
  751.  ; Es wird 8 mal aufgerufen, um 128 befehle zu installieren.
  752.  
  753. INIT_COPY:  MACRO
  754.  move.l (a0)+,(a2)+
  755.  move.l (a0)+,(a2)+
  756.  move.l (a0)+,(a2)+
  757.  move.l (a0)+,(a2)+
  758.  move.l (a0)+,(a2)+
  759.  move.l (a0)+,(a2)+
  760.  move.l (a0)+,(a2)+
  761.  move.l (a0)+,(a2)+
  762.  move.l (a0)+,(a2)+
  763.  move.l (a0)+,(a2)+
  764.  move.l (a0)+,(a2)+
  765.  move.l (a0)+,(a2)+
  766.  move.l (a0)+,(a2)+
  767.  move.l (a0)+,(a2)+
  768.  move.l (a0)+,(a2)+
  769.  move.l (a0)+,(a2)+
  770.  endm
  771.  
  772. CopyMemFast:
  773.  tst.l d0                          ; Ist etwas zu kopieren ?
  774.  beq CopyMemFast_Ende              ; Nein, dann springe zum Ende
  775.  lsr.l #7,d0                       ; Länge durch 128 dividieren
  776.  lsr.l #2,d0                       ; Länge durch 4 dividieren
  777.  subq.l #1,d0                      ; 1 subtrahieren
  778. CopyMemFast_Loop:                  ; Kopierschleife
  779.  INIT_COPY
  780.  INIT_COPY
  781.  INIT_COPY
  782.  INIT_COPY
  783.  INIT_COPY
  784.  INIT_COPY
  785.  INIT_COPY
  786.  INIT_COPY
  787.  dbra d0,CopyMemFast_Loop          ; Zurückzählen
  788. CopyMemFast_Ende:                  ; Ende:
  789.  rts                               ; Rücksprung
  790.  
  791. MyStop:                            ; Ausführung anhalten
  792.  bset #TDUB_STOPPED,UNIT_FLAGS(a3) ; Flag setzen
  793.  bsr TermIO                        ; Zu TermIO springen
  794.  rts                               ; Rücksprung
  795.  
  796. Start:                             ; Ausführung weiterführen
  797.  bsr InternalStart                 ; Zu InternalStart springen
  798.  move.l a2,a1                      ; IOStdReq nach a1
  799.  bsr TermIO                        ; Zu TermIO springen
  800.  rts                               ; Rücksprung
  801.  
  802. InternalStart:                     ; Startroutine:
  803.  bclr #TDUB_STOPPED,UNIT_FLAGS(a3) ; Stop-Flag löschen
  804.  move.l MP_SIGTASK(a3),a1          ; Task nach a1
  805.  clr.l d0                          ; d0=0
  806.  move.b MP_SIGBIT(a3),d1           ; Signalbit nach d1
  807.  bset d1,d0                        ; Bit setzen
  808.  LINKSYS Signal,td_SysLib(a6)      ; Signal setzen
  809.  rts                               ; Rücksprung
  810.  
  811. Flush:                             ; Alle Befehle als Abgebrochen zurück
  812.  movem.l d2/a6,-(a7)               ; Register retten
  813.  move.l td_SysLib(a6),a6           ; ExecBase nach a6
  814.  FORBID
  815. Flush_Loop:                        ; Schleife:
  816.  move.l a3,a0                      ; Unit nach a0
  817.  CALLSYS GetMsg                    ; Message holen
  818.  tst.l  d0                         ; Message angekommen ?
  819.  beq.s Flush_end                   ; Nein, dann Ende
  820.  move.l d0,a1                      ; IOStdReq nach a1
  821.  move.b #IOERR_ABORTED,IO_ERROR(a1); Fehler nach io_Error
  822.  CALLSYS ReplyMsg                  ; Message zurückschicken
  823.  bra.s Flush_Loop                  ; Zu Schleife springen
  824. Flush_end: PERMIT
  825.  movem.l (a7)+,d2/a6               ; Register freigeben
  826.  move.l a2,a1                      ; IOStdReq nach a1
  827.  bsr TermIO                        ; Zu TermIO springen
  828.  rts                               ; Rücksprung
  829.  
  830. Seek:                              ; Schreib/Lesekopf positionieren
  831.  move.l IO_OFFSET(a1),tdu_Position(a3) ; Position eintragen
  832. AddChangeInt:                      ; Der Seek-Befehl endet wie die
  833. RemChangeInt:                      ; folgenden Befehle.
  834. Update:                            ; Nicht gültige Befehle, die jedoch
  835. Clear:                             ; keinen Fehler zurückgeben dürfen, da
  836. Remove:                            ; diese von DOS aufgerufen werden,
  837.  clr.b IO_ERROR(a1)                ; weil sie bei einem Disketten-
  838.  bsr TermIO                        ; laufwerk eine Bestimmte Funktion
  839.  rts                               ; haben.
  840.  
  841. Motor:                             ; Motor ein- und Ausschalten
  842.  move.l IO_LENGTH(a1),d0           ; Da Ram-Disks keine Motoren
  843.  cmp.l #1,d0                       ; besitzen wird hier auch
  844.  beq 1$                            ; nichts ausgeschaltet.
  845.  move.l #1,d0                      ; DOS verlangt in Actual den
  846.  bra 2$                            ; vorherigen Status des Motors.
  847. 1$:                                ; Es wird der Gegenteilige 
  848.  move.l #0,d0                      ; Status aus io_Length in 
  849. 2$:                                ; io_Actual übergeben.
  850.  move.l d0,IO_ACTUAL(a1)           ; Alter Status in Actual
  851.  clr.b IO_ERROR(a1)                ; Kein Fehler
  852.  bsr TermIO                        ; Zu TermIO springen
  853.  rts                               ; Rücksprung
  854.  
  855. Status:                            ; Anzahl der Diskettenwechsel
  856.  move.l #0,IO_ACTUAL(a1)           ; Diskette Schreibgeschützt ?
  857.  move.b #0,IO_ERROR(a1)            ; Diskette eingelegt ?
  858.  bsr TermIO                        ; Da alle Befehle in einer Ram-Disk 0
  859.  rts                               ; ergeben, wird nur eine Routine benötigt.
  860.  
  861.  ; ==========================================================================
  862.  
  863.  ; Hier beginnen die Routinen für die Prozesse.
  864.  ; Der Funktion CreateProc wird ein Zeiger auf TurboProc_SegList
  865.  ; übergeben. Als erster Befehl in der SegList muß "dc.l 0" stehen,
  866.  ; weil an dieser Stelle ein Zeiger auf das nächste Segment erwartet wird!
  867.  
  868.  CNOP 0,4                          ; Auf Langwortgröße erweitern
  869. TurboProc_SegList:                 ; Anfang der SegList
  870.  dc.l 0                            ; Zeiger auf nächstes Segment (=NULL)
  871.  
  872. Proc_Begin:                        ; Code der SegList
  873.  move.l $4,a6                      ; ExecBase nach a6
  874.  sub.l a1,a1                       ; a1=NULL
  875.  CALLSYS FindTask                  ; Task suchen
  876.  move.l d0,a0                      ; Task nach a0
  877.  move.l d0,a4                      ; und a4
  878.  lea pr_MsgPort(a0),a0             ; der MsgPort von a0 nach a0
  879.  CALLSYS WaitPort                  ; Auf Nachricht warten
  880.  move.l d0,a1                      ; Nachricht in a1
  881.  move.l d0,a2                      ; und a2
  882.  CALLSYS Remove                    ; Nachricht löschen
  883.  move.l tdm_Device(a2),a5          ; Device nach a5
  884.  move.l tdm_Unit(a2),a3            ; Unit nach a3
  885.  moveq #-1,d0                      ; -1 nach d0
  886.  CALLSYS AllocSignal               ; Freies Signal holen
  887.  move.b d0,MP_SIGBIT(a3)           ; Signal in SigBit
  888.  move.b #PA_SIGNAL,MP_FLAGS(a3)    ; Flags = PA_SIGNAL
  889.  clr.l d7                          ; d7=0
  890.  bset d0,d7                        ; Signal in d7 setzen
  891.  bra.s Proc_CheckStatus            ; Zu Proc_CheckStatus springen
  892.  
  893. Proc_MainLoop:                     ; Hauptschleife
  894.  move.l d7,d0                      ; Signal nach d7
  895.  CALLSYS Wait                      ; Auf Signal warten
  896. Proc_CheckStatus:                  ; Proc_CheckStatus:
  897.  btst #TDUB_STOPPED,UNIT_FLAGS(a3) ; Ist Stop-Flag gesetzt ?
  898.  bne.s Proc_MainLoop               ; Ja, dann zur Hauptschleife
  899.  bset #UNITB_ACTIVE,UNIT_FLAGS(a3) ; Ist Task aktiv ?
  900.  bne.s Proc_MainLoop               ; Ja, dann warten, bis Task frei wird
  901.  
  902. Proc_NextMsg:
  903.  move.l a3,a0                      ; Zeiger auf Port in a0
  904.  CALLSYS GetMsg                    ; Auf Message warten
  905.  tst.l d0                          ; Message angekommen ?
  906.  beq.s Proc_Unlock                 ; Nein, dann springe
  907.  move.l d0,a1                      ; Message nach a1
  908.  exg a5,a6                         ; a5 mit a6 vertauschen
  909.  bsr PerformIO                     ; Befehl auswerten
  910.  exg a5,a6                         ; a5 mit a6 vertauschen
  911.  bra Proc_NextMsg                  ; Nächste Message bearbeiten
  912.  
  913. Proc_Unlock:
  914.  bclr #UNITB_ACTIVE,UNIT_FLAGS(a3) ; Aktive-Bit löschen
  915.  bclr #UNITB_INTASK,UNIT_FLAGS(a3) ; Intask-Bit löschen
  916.  bra Proc_MainLoop                 ; Zur Hauptschleife springen
  917.  
  918.  END
  919.  
  920.